package com.whenjun.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.idev.excel.FastExcel;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ifootbook.util.*;
import com.whenjun.dto.kq.*;
import com.whenjun.entity.Kq;
import com.whenjun.mapper.KqMapper;
import com.whenjun.service.IKqService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.whenjun.util.ExportExcelUtils;
import com.whenjun.util.IPageUtil;
import com.whenjun.util.SaTokenUtil;
import com.whenjun.util.TransUtil;
import lombok.Data;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author whenjun
 * @since 2024-02-28
 */
@Service
public class KqServiceImpl extends ServiceImpl<KqMapper, Kq> implements IKqService {

    /**
     *  根据日期初始化考勤数据表
     * @param yyyyMMdd
     */
    @Transactional
    public void initKqData(String yyyyMMdd) {
        if (EmptyUtil.isEmpty(yyyyMMdd)) {
            yyyyMMdd = TimeUtil.formatDate(TimeUtil.getLastDate(new Date()), DateStyle.YYYY_MM_DD);
        }
        try {
            this.baseMapper.initKqData(yyyyMMdd);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Transactional
    public List<KqDoorData> getByDateAndGroupCode(String yyyyMMdd, String groupCode) {
        List<KqDoorData> kqDoorData = this.getBaseMapper().selectByDateAndGroupCode(yyyyMMdd, groupCode);
        return kqDoorData;
    }

    @Transactional
    public IPage<KqDTO> Kqs(KqReq kqReq) {
        IPage<Kq> page = new Page<>(kqReq.getPage(), kqReq.getSize());

        kqReq.setStartDay(EmptyUtil.isEmpty(kqReq.getStartDay()) ? null : kqReq.getStartDay() + " 00:00:00");
        kqReq.setEndDay(EmptyUtil.isEmpty(kqReq.getEndDay()) ? null : kqReq.getEndDay() + " 23:59:59");

        LocalDateTime startDate = LocalDateTimeUtil.parse(kqReq.getStartDay(), DateStyle.YYYY_MM_DD_HH_MM_SS.getValue());
        LocalDateTime endDate = LocalDateTimeUtil.parse(kqReq.getEndDay(), DateStyle.YYYY_MM_DD_HH_MM_SS.getValue());


        IPage<Kq> kqIPage = this.lambdaQuery()
                .ge(!EmptyUtil.isEmpty(kqReq.getStartDay()), Kq::getDate, kqReq.getStartDay())
                .le(!EmptyUtil.isEmpty(kqReq.getEndDay()), Kq::getDate, kqReq.getEndDay())
                .orderByDesc(Kq::getDate)
                .page(page);

        IPage<KqDTO> kqDTOIPage = new Page<>();
        kqDTOIPage.setTotal(kqIPage.getTotal());
        kqDTOIPage.setCurrent(kqIPage.getCurrent());
        kqDTOIPage.setSize(kqIPage.getSize());
        kqDTOIPage.setPages(kqIPage.getPages());

        List<KqDTO> kqDTOS = new ArrayList<>();

        for (Kq kq : kqIPage.getRecords()) {
            KqDTO kqDTO = BeanUtil.copyProperties(kq, KqDTO.class);
            kqDTO.setCountKqTimeStr(TransUtil.convertSecondsToTime(kq.getCountKqTime()));
            kqDTO.setRestSumTimeStr(TransUtil.convertSecondsToTime(kq.getRestSumTime()));
            kqDTO.setJiabanTimeStr(TransUtil.convertSecondsToTime(kq.getJiabanTime()));

            if (!EmptyUtil.isEmpty(kq.getKqState())) {
                kqDTO.setKqStateList(JSON.parseArray(kq.getKqState()));
            }
            if (!EmptyUtil.isEmpty(kq.getKqStateName())) {
                kqDTO.setKqStateNameList(JSON.parseArray(kq.getKqStateName()));
            }
            if(kq.getDakaShangbanTime() != null) {
                kqDTO.setDakaShangbanTime(TimeUtil.getDate(kq.getDakaShangbanTime()));
            }
            if(kq.getDakaXiabanTime() != null) {
                kqDTO.setDakaXiabanTime(TimeUtil.getDate(kq.getDakaXiabanTime()));
            }

            kqDTOS.add(kqDTO);
        }
        kqDTOIPage.setRecords(kqDTOS);

        return kqDTOIPage;
    }

    @Transactional
    public IPage<KqDTO> kqExport(String startDay, String endDay) {

        IPage<Kq> page = new Page<>(1, 2147483647);


        startDay = EmptyUtil.isEmpty(startDay) ? null : startDay + " 00:00:00";
        endDay = EmptyUtil.isEmpty(endDay) ? null : endDay + " 23:59:59";

        LocalDateTime startDate = LocalDateTimeUtil.parse(startDay, DateStyle.YYYY_MM_DD_HH_MM_SS.getValue());
        LocalDateTime endDate = LocalDateTimeUtil.parse(endDay, DateStyle.YYYY_MM_DD_HH_MM_SS.getValue());


        IPage<Kq> kqIPage = this.lambdaQuery()
                .ge(!EmptyUtil.isEmpty(startDate), Kq::getDate, startDay)
                .le(!EmptyUtil.isEmpty(endDate), Kq::getDate, endDay)
                .orderByDesc(Kq::getDate)
                .page(page);

        IPage<KqDTO> kqDTOIPage = new Page<>();
        kqDTOIPage.setTotal(kqIPage.getTotal());
        kqDTOIPage.setCurrent(kqIPage.getCurrent());
        kqDTOIPage.setSize(kqIPage.getSize());
        kqDTOIPage.setPages(kqIPage.getPages());

        List<KqDTO> kqDTOS = new ArrayList<>();

        for (Kq kq : kqIPage.getRecords()) {
            KqDTO kqDTO = BeanUtil.copyProperties(kq, KqDTO.class);
            kqDTO.setCountKqTimeStr(TransUtil.convertSecondsToTime(kq.getCountKqTime()));
            kqDTO.setRestSumTimeStr(TransUtil.convertSecondsToTime(kq.getRestSumTime()));
            kqDTO.setJiabanTimeStr(TransUtil.convertSecondsToTime(kq.getJiabanTime()));

            if (!EmptyUtil.isEmpty(kq.getKqState())) {
                kqDTO.setKqStateList(JSON.parseArray(kq.getKqState()));
            }
            if (!EmptyUtil.isEmpty(kq.getKqStateName())) {
                kqDTO.setKqStateNameList(JSON.parseArray(kq.getKqStateName()));
            }
            if(kq.getDakaShangbanTime() != null) {
                kqDTO.setDakaShangbanTime(TimeUtil.getDate(kq.getDakaShangbanTime()));
            }
            if(kq.getDakaXiabanTime() != null) {
                kqDTO.setDakaXiabanTime(TimeUtil.getDate(kq.getDakaXiabanTime()));
            }

            kqDTOS.add(kqDTO);
        }
        kqDTOIPage.setRecords(kqDTOS);

        return kqDTOIPage;
    }

    @Transactional
    public void kqService(KqUpdReq kqUpdReq) {
        Kq kq = this.getById(kqUpdReq.getId());
        if (kq == null) {
            throw new FootBookException("id错误");
        }

        String userId = SaTokenUtil.getUserId();
        LocalDateTime now = LocalDateTime.now();

        kq.setKqState(kqUpdReq.getKqState());
        kq.setRemark(kqUpdReq.getRemark());
        kq.setUpdateTime(now);
        kq.setUpdateUser(userId);

        this.updateById(kq);
    }

    @Transactional
    public void KqExport(String startDay, String endDay, HttpServletResponse response) {

        List<KqDTO> kqDTOS = this.kqExport(startDay, endDay).getRecords();

        //文件名
        String excelName = startDay + "-" + endDay + "月" + "考勤数据.xls";

        String sheetName = "考勤数据";
        List<LinkedHashMap<String, String>> fieldMapList = new ArrayList<LinkedHashMap<String,String>>();
        //sheet表头字段名
        LinkedHashMap<String, String> fieldMap = new LinkedHashMap<String, String>();
        fieldMap.put("date", "考勤日期");
        fieldMap.put("jobNo", "工号");
        fieldMap.put("personName", "姓名");
        fieldMap.put("departmentName", "人员部门");
        fieldMap.put("departmentGroupName", "人员班组");
        fieldMap.put("departmentGroupShangbanTime", "班组上班时间");
        fieldMap.put("departmentGroupXiabanTime", "班组下班时间");
        fieldMap.put("kqStateNameList", "考勤状态");
        fieldMap.put("dakaShangbanNum", "上班打卡次数");
        fieldMap.put("dakaXiabanNum", "下班打卡次数");
        fieldMap.put("dakaShangbanTime", "上班打卡时间");
        fieldMap.put("dakaXiabanTime", "下班打卡时间");
        fieldMap.put("jiabanTimeStr", "加班时长（时分秒");
        fieldMap.put("countKqTimeStr", "统计考勤总时长（时分秒）");
        fieldMap.put("restSumTimeStr", "考勤日休息总时长（时分秒）");
        fieldMap.put("remark", "备注");

        //导出
        ExportExcelUtils.export(excelName,sheetName, kqDTOS, fieldMap, response);
    }

    @Transactional
    public List<Kq> getByDate(String yyyyMMdd) {
        return this.lambdaQuery().eq(Kq::getDate, yyyyMMdd).list();
    }


    @Override
    @Transactional
    public void download(HttpServletResponse response, String month) throws ParseException, IOException {
        // 设置响应头，告诉浏览器是 Excel 文件
        String excelName = URLEncoder.encode("考勤数据_" + month + ".xlsx", "UTF-8");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + excelName);

        Date firstMonthDay = TimeUtil.getFirstMonthDay(month);
        Date lastMonthDay = TimeUtil.getLastMonthDay(month);

        SimpleDateFormat dateFormat = new SimpleDateFormat(DateStyle.YYYY_MM_DD.getValue());
        String startDay = dateFormat.format(firstMonthDay);
        String endDay = dateFormat.format(lastMonthDay);


        List<KqV2DTO> kqV2DTOS = this.getBaseMapper().KqV2DTO(startDay, endDay);

        // 直接将 Excel 写入 response 输出流
        FastExcel.write(response.getOutputStream(), KqV2DTO.class).sheet("考勤数据").doWrite(kqV2DTOS);

    }
}
